﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using NHibernate;
using NHibernate.Cfg;
using NHibernate.Mapping.Attributes;
using org.iringtools.utility;
using System.IO;
using org.iringtools.library;
using org.iringtools.adapter;
using System.Collections.Specialized;

namespace HelloNHibernate
{
  #region Commented code
  //public class Program
  //{
  //  static ISessionFactory factory;

  //  static void Main()
  //  {
  //    CreateLineAndSaveToDatabase();
  //    //UpdateTobinAndAssignPierreHenriAsManager();
  //    LoadLinesFromDatabase();
  //    Console.WriteLine("Press any key to exit...");
  //    Console.ReadKey();
  //  }

  //  static void CreateLineAndSaveToDatabase()
  //  {
  //    Line line = new Line();
  //    line.Tag = "MY-LINE-0002";
  //    line.JobNumber = "PROJ";
  //    using (ISession session = OpenSession())
  //    {
  //      using (ITransaction transaction = session.BeginTransaction())
  //      {
  //        session.Save(line);
  //        transaction.Commit();
  //      }
  //      Console.WriteLine("Saved line to the database");
  //    }
  //  }
  //  static ISession OpenSession()
  //  {
  //    if (factory == null)
  //    {
  //      Configuration c = new Configuration();
  //      MemoryStream stream = HbmSerializer.Default.Serialize(typeof(Line));
  //      Utility.WriteStream(stream, "Test.hbml");
  //      c.AddInputStream(stream);
  //      factory = c.BuildSessionFactory();
  //    }
  //    return factory.OpenSession();
  //  }

  //  static void LoadLinesFromDatabase()
  //  {
  //    using (ISession session = OpenSession())
  //    {
  //      IQuery query = session.CreateQuery(
  //      "from Line as line order by line.Tag asc");
  //      IList<Line> foundLines = query.List<Line>();
  //      Console.WriteLine("\n{0} employees found:",
  //      foundLines.Count);
  //      foreach (Line line in foundLines)
  //        Console.WriteLine(line.Tag);
  //    }
  //  }

  //  //static void UpdateTobinAndAssignPierreHenriAsManager()
  //  //{
  //  //  using (ISession session = OpenSession())
  //  //  {
  //  //    using (ITransaction transaction = session.BeginTransaction())
  //  //    {
  //  //      IQuery q = session.CreateQuery(
  //  //      "from Employee where name = 'Tobin Harris'");
  //  //      Employee tobin = q.List<Employee>()[0];
  //  //      tobin.name = "Tobin David Harris";
  //  //      Employee pierreHenri = new Employee();
  //  //      pierreHenri.name = "Pierre Henri Kuate";
  //  //      tobin.manager = pierreHenri;
  //  //      transaction.Commit();
  //  //      Console.WriteLine("Updated Tobin and added Pierre Henri");
  //  //    }
  //  //  }
  //  //}
  //}
  #endregion


  public class Program
  {
    static void Main()
    {
      
      AdapterSettings settings = new AdapterSettings(new NameValueCollection());
      //DataLayer dataLayer = new DataLayer(settings);
      NHibernateDataLayer dataLayer = new  NHibernateDataLayer();
      #region Get
      Dictionary<string, object> queryProperties = new Dictionary<string, object>();
      //queryProperties.Add("Tag", "1-AB-L-001");
      IList<Line> lines = dataLayer.GetList<Line>(queryProperties);
      #endregion

      #region Add
      //Line line = new Line();
      //line.Tag = "1-AB-L-005";
      //line.Diameter = "5";
      //dataLayer.Add<Line>(line);
      #endregion

      #region Update
      //Line line = new Line();
      //line.Tag = "1-AB-L-008";
      //line.Diameter = "10";
      //dataLayer.Update<Line>(line);
      #endregion

      #region Post
      Line line = new Line();
      line.Tag = "1-AB-L-008";
      line.Diameter = "5";
      dataLayer.Post<Line>(line);
      #endregion

    }
  }
}
  
  public class NHibernateDataLayer
  {
    private ISessionFactory factory;

    private ISession OpenSession<T>()
    {
      if (factory == null)
      {
        Configuration c = new Configuration();
        MemoryStream stream = HbmSerializer.Default.Serialize(typeof(T));
        c.AddInputStream(stream);
        factory = c.BuildSessionFactory();
      }
      return factory.OpenSession();
    }

    public T Get<T>(Dictionary<string, object> queryProperties)
    {
      try
      {
        StringBuilder queryString = new StringBuilder();
        using (ISession session = OpenSession<T>())
        {
          queryString.Append(" from " + typeof(T).Name + " as " + typeof(T).Name);
          if (queryProperties != null && queryProperties.Count > 0)
          {
            queryString.Append(" where ");
            foreach (KeyValuePair<string, object> keyValuePair in queryProperties)
            {
              queryString.Append(typeof(T).Name + "." + keyValuePair.Key + "='" + keyValuePair.Value + "'");
              queryString.Append(" and ");
            }
            queryString.Replace(" and ", "", queryString.Length - 5, 5);
          }

          IQuery query = session.CreateQuery(queryString.ToString());
          return query.List<T>().FirstOrDefault<T>();
        }
      }
      catch (Exception exception)
      {
        throw new Exception("Error while getting data of type " + typeof(T).Name + ".", exception);
      }
    }

    public IList<T> GetList<T>()
    {
      return GetList<T>(null);
    }

    public IList<T> GetList<T>(Dictionary<string, object> queryProperties)
    {
      try
      {
        StringBuilder queryString = new StringBuilder();
        using (ISession session = OpenSession<T>())
        {
          queryString.Append(" from " + typeof(T).Name + " as " + typeof(T).Name);
          if (queryProperties != null && queryProperties.Count > 0)
          {
            queryString.Append(" where ");
            foreach (KeyValuePair<string, object> keyValuePair in queryProperties)
            {
              queryString.Append(typeof(T).Name + "." + keyValuePair.Key + "='" + keyValuePair.Value + "'");
              queryString.Append(" and ");
            }
            queryString.Replace(" and ", "", queryString.Length - 5, 5);
          }
          IQuery query = session.CreateQuery(queryString.ToString());
          return query.List<T>();
        }
      }
      catch (Exception exception)
      {
        throw new Exception("Error while getting data of type " + typeof(T).Name + ".", exception);
      }
    }

    public Response Post<T>(T graph)
    {
      Response response;
      try
      {
        response = new Response();
        using (ISession session = OpenSession<T>())
        {
          using (ITransaction transaction = session.BeginTransaction())
          {
            try
            {
              response = Update<T>(graph);
              response.Add("Records of type " + typeof(T).Name + " have been posted successfully");
            }
            catch (Exception)
            {
              response = Add<T>(graph);
              response.Add("Records of type " + typeof(T).Name + " have been added successfully");
            }
          }
          response.Add("Records (" + typeof(T).Name + ") have been added succesfully");

        }
        return response;
      }
      catch (Exception exception)
      {
        throw new Exception("Error while posting data of type " + typeof(T).Name + ".", exception);
      }
    }

    public Response PostList<T>(List<T> graphList)
    {
      Response response;
      try
      {
        response = new Response();
        foreach (T graph in graphList)
        {
          try
          {
            Response responseGraph = Post<T>(graph);
            response.Add(responseGraph[0]);
          }
          catch (Exception exception)
          {
            response.Add(exception.ToString());
          }
        }
        return response;
      }
      catch (Exception exception)
      {
        throw new Exception("Error while posting data of type " + typeof(T).Name + ".", exception);
      }
    }
    public Response Add<T>(T graph)
    {
      Response response;
      try
      {
        response = new Response();
        using (ISession session = OpenSession<T>())
        {
          using (ITransaction transaction = session.BeginTransaction())
          {
            session.Save(graph);
            transaction.Commit();
          }
          response.Add("Records (" + typeof(T).Name + ") have been added succesfully");

        }
        return response;
      }
      catch (Exception exception)
      {
        throw new Exception("Error while posting data of type " + typeof(T).Name + ".", exception);
      }
    }

    public Response Update<T>(T graph)
    {
      Response response;
      try
      {
        response = new Response();
        using (ISession session = OpenSession<T>())
        {
          using (ITransaction transaction = session.BeginTransaction())
          {
            session.Update(graph);
            transaction.Commit();
          }
          response.Add("Records (" + typeof(T).Name + ") have been updated succesfully");

        }
        return response;
      }
      catch (Exception exception)
      {
        throw new Exception("Error while updating data of type " + typeof(T).Name + ".", exception);
      }
    }

    public Response Delete<T>(T graph)
    {
      Response response;
      try
      {
        response = new Response();
        using (ISession session = OpenSession<T>())
        {
          using (ITransaction transaction = session.BeginTransaction())
          {
            session.Delete(graph);
            transaction.Commit();
          }
          response.Add("Records (" + typeof(T).Name + ") have been deleted succesfully");

        }
        return response;
      }
      catch (Exception exception)
      {
        throw new Exception("Error while deleting data of type " + typeof(T).Name + ".", exception);
      }
    }
  }
    

  
